package view.GUI.mainView;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.controlsfx.dialog.Dialogs;

import enums.GUIText;
import enums.Message;
import enums.PaymentType;
import view.GUI.otherView.Logout;
import view.GUI.otherView.PaycheckView;
import model.data.wrapper.ToPay;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.Separator;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;

/**
 * Provides a GridPane showing the values of the given input.
 * <p>
 * Is embedded to the <code>MainView</code>.
 * 
 * @version %I%, %G%
 * @see MainView
 * @see KindVBox
 */
public final class PaymentGrid extends GridPane {

	private static Logger log = LogManager.getLogger("ERROR");
	private static Logger infoLog = LogManager.getLogger("INFO");

	private static PaymentGrid instance;

	private Label lblToPay;
	private Label lblDepositionBack;
	private Label lblDeposition;
	private Label lblSum;
	private Label lblGiven;
	private Label lblBack;
	private Label lblBackCount;
	private Label lblPayCount;
	private Label lblDepositionCount;
	private Label lblDepositionBackCount;
	private Label lblSumCount;

	private TextField txtGiven;
	private Button btnPay;
	private Button btnClear;
	private MainView mainView;
	private ToPay toPay;
	private Separator sep;
	private Button btnLogout;

	private int rowCounter;

	private PaymentGrid(MainView mainView) {

		this.rowCounter = 1;
		this.setAlignment(Pos.CENTER_RIGHT);
		this.mainView = mainView;
		createWidgets();
		addWidgets();
		setupInteraction();
		setupLayout();
	}

	private void setupLayout() {
		this.getStyleClass().add("maingrid");
		lblSum.setId("SumToPay");
		lblSumCount.getStyleClass().addAll("highlight", "double-underline");
		sep.getStyleClass().add("separator");
		GridPane.setColumnSpan(sep, 3);
		btnLogout.setId("logout");
		txtGiven.setPrefSize(50, 25);
	}

	/**
	 * Gets the instance of this class. Is implemented as Singleton.
	 * 
	 * @param mainView reference to the mainView
	 * @return instance of this class
	 */
	public static PaymentGrid getInstance(MainView mainView) {

		if (instance == null) {
			instance = new PaymentGrid(mainView);
		}
		return instance;
	}

	/**
	 * Shows the updated values of the given input
	 */
	public void showComputedValue() {

		this.toPay = mainView.getComputedInput();

		lblDepositionBackCount.setText(MainView.formatNumber(toPay.getDepositBackValue()));
		lblPayCount.setText(MainView.formatNumber((toPay.getDrinkValue()) + toPay.getGroceryValue() + toPay.getOtherValue()));
		lblSumCount.setText(MainView.formatNumber(toPay.getSum()));
		lblDepositionCount.setText(MainView.formatNumber(toPay.getDepositValue()));
		// enable textfield if customer pays with cash
		if (toPay.getSum() != 0 && toPay.getCustomer().getPayment().equals(PaymentType.CASH)) {
			txtGiven.setDisable(false);
		} else {
			txtGiven.setDisable(true);
		}
		// if nothing was entered disable pay button
		if (toPay.getDepositBackValue() == 0 && toPay.getDrinkValue() == 0 && toPay.getGroceryValue() == 0 && toPay.getOtherValue() == 0
				&& !mainView.getValSup().getValidationResult().getErrors().isEmpty()) {
			btnPay.setDisable(true);
		} else {
			btnPay.setDisable(false);
		}

	}

	/**
	 * Resets the label indicating the values of the input.
	 */
	public void resetInput() {

		lblPayCount.setText(MainView.formatNumber(0.00));
		lblSumCount.setText(MainView.formatNumber(0.00));
		lblDepositionBackCount.setText(MainView.formatNumber(0.00));
		lblBackCount.setText(MainView.formatNumber(0.00));
		lblDepositionCount.setText(MainView.formatNumber(0.00));
		toPay = null;
		txtGiven.clear();
		btnPay.setDisable(true);
		txtGiven.setDisable(true);
	}

	private void setupInteraction() {
		btnLogout.setOnAction(new EventHandler<ActionEvent>() {

			@Override
			public void handle(ActionEvent arg0) {
				new Logout(mainView.getPrimaryStage());
			}
		});
		btnPay.setOnAction(new EventHandler<ActionEvent>() {

			@Override
			public void handle(ActionEvent event) {

				if (mainView.getValSup().invalidProperty().getValue()) {
					Dialogs.create().owner(mainView.getPrimaryStage()).title("Error").message(Message.ERROR.toString()).showError();
					infoLog.info("Error popup shown");
				} else {
					new PaycheckView(toPay, mainView.getPrimaryStage(), mainView);
				}
			}
		});
		txtGiven.textProperty().addListener(new ChangeListener<String>() {

			@Override
			public void changed(ObservableValue<? extends String> arg0, String arg1, String newValue) {

				try {
					if (newValue.isEmpty()) {
						lblBackCount.setText(MainView.formatNumber(0.00));
					} else {
						String back = MainView.formatNumber(Double.parseDouble(newValue) - toPay.getSum());
						lblBackCount.setText(back);
					}
				} catch (NumberFormatException e) {
					log.error(e.getMessage());
				}
			}
		});
		btnClear.setOnAction(new EventHandler<ActionEvent>() {

			@Override
			public void handle(ActionEvent arg0) {
				mainView.resetInput();
			}
		});
	}

	private void addWidgets() {

		this.add(lblToPay, 1, rowCounter);
		this.add(lblPayCount, 2, rowCounter++);
		this.add(lblDeposition, 1, rowCounter);
		this.add(lblDepositionCount, 2, rowCounter++);
		this.add(lblDepositionBack, 1, rowCounter);
		this.add(lblDepositionBackCount, 2, rowCounter++);
		this.add(lblSum, 1, rowCounter);
		this.add(lblSumCount, 2, rowCounter++);
		this.add(sep, 0, rowCounter++);
		GridPane.setColumnSpan(sep, 2);
		this.add(lblGiven, 1, rowCounter);
		this.add(txtGiven, 2, rowCounter++);
		this.add(lblBack, 1, rowCounter);
		this.add(lblBackCount, 2, rowCounter++);
		this.add(btnPay, 1, rowCounter);
		this.add(btnClear, 2, rowCounter++);
		this.add(btnLogout, 2, rowCounter++);
	}

	private void createWidgets() {

		lblToPay = new Label(GUIText.TOPAY.toString());
		lblDepositionBack = new Label(GUIText.DEPOSITBACK.toString());
		lblSum = new Label(GUIText.WHOLE.toString());
		lblGiven = new Label(GUIText.GIVEN.toString());
		lblBack = new Label(GUIText.CHANGE.toString());
		lblBackCount = new Label(MainView.formatNumber(0.00));
		lblPayCount = new Label(MainView.formatNumber(0.00));
		lblDepositionBackCount = new Label(MainView.formatNumber(0.00));
		lblSumCount = new Label(MainView.formatNumber(0.00));
		btnPay = new Button(GUIText.PAY.toString());
		btnClear = new Button(GUIText.DELETE.toString());
		txtGiven = new TextField();
		btnPay.setDisable(true);
		txtGiven.setDisable(true);
		lblDeposition = new Label(GUIText.DEPOSIT.toString());
		lblDepositionCount = new Label(MainView.formatNumber(0.00));
		sep = new Separator();
		btnLogout = new Button(GUIText.LOGOUT.toString());
	}
}
